home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MPW C++ / MPW C++ 3.1 / Examples / CPlusExamples / ShapesApp.cp < prev    next >
Text File  |  1990-09-11  |  10KB  |  371 lines

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    MultiFinder-Aware Simple Shapes Sample Application
  4. #
  5. #    CPlusShapesApp
  6. #
  7. #    This file: ShapesApp.cp - Implementation of the TShapesApp Class
  8. #
  9. #    Copyright © 1988 Apple Computer, Inc.
  10. #    All rights reserved.
  11. #
  12. #    Versions:    1.0                 3/89
  13. #
  14. #    Components:
  15. #            CPlusShapesApp.make        March 1, 1989
  16. #            TApplicationCommon.h    March 1, 1989
  17. #            TApplication.h            March 1, 1989
  18. #            TDocument.h                March 1, 1989
  19. #            ShapesAppCommon.h        March 1, 1989
  20. #            ShapesApp.h                March 1, 1989
  21. #            ShapesDocument.h        March 1, 1989
  22. #            TApplication.cp            March 1, 1989
  23. #            TDocument.cp            March 1, 1989
  24. #            ShapesApp.cp            March 1, 1989
  25. #            ShapesDocument.cp        March 1, 1989
  26. #            TApplication.r            March 1, 1989
  27. #            ShapesApp.r                March 1, 1989
  28. #
  29. #   There are four main classes in this program. Each of
  30. #   these classes has a definition (.h) file and an
  31. #   implementation (.cp) file.  
  32. #   
  33. #   The TApplication class does all of the basic event
  34. #   handling and initialization necessary for Mac Toolbox
  35. #   applications. It maintains a list of TDocument objects,
  36. #   and passes events to the correct TDocument class when
  37. #   apropriate. 
  38. #   
  39. #   The TDocument class does all of the basic document
  40. #   handling work. TDocuments are objects that are
  41. #   associated with a window. Methods are provided to deal
  42. #   with update, activate, mouse-click, key down, and other
  43. #   events. Some additional classes which implement a
  44. #   linked list of TDocument objects are provided. 
  45. #   
  46. #   The TApplication and TDocument classes together define
  47. #   a basic framework for Mac applications, without having
  48. #   any specific knowledge about the type of data being
  49. #   displayed by the application's documents. They are a
  50. #   (very) crude implementation of the MacApp application
  51. #   model, without the sophisticated view heirarchies or
  52. #   any real error handling. 
  53. #   
  54. #   The TShapesApp class is a subclass of TApplication. It
  55. #   overrides several TApplication methods, including those
  56. #   for handling menu commands and cursor adjustment, and
  57. #   it does some necessary initialization.
  58. #   
  59. #   The TShapesDocument class is a subclass of TDocument. This
  60. #   class contains most of the special purpose code for
  61. #   shape drawing. In addition to overriding several of the
  62. #   TDocument methods, it defines a few additional
  63. #   methods which are used by the TShapesApp class to get
  64. #   information on the document state.  
  65. #
  66. #------------------------------------------------------------------------------*/
  67. #include <Types.h>
  68. #include <QuickDraw.h>
  69. #include <Fonts.h>
  70. #include <Events.h>
  71. #include <Controls.h>
  72. #include <Windows.h>
  73. #include <Menus.h>
  74. #include <TextEdit.h>
  75. #include <Dialogs.h>
  76. #include <Desk.h>
  77. #include <Scrap.h>
  78. #include <ToolUtils.h>
  79. #include <Memory.h>
  80. #include <SegLoad.h>
  81. #include <Files.h>
  82. #include <OSUtils.h>
  83. #include <Traps.h>
  84.  
  85. // our class definitions
  86. #include "ShapesDocument.h"
  87. #include "ShapesApp.h"
  88.  
  89. // ExtremeNeg and ExtremePos are used to set up wide open rectangles and regions.
  90. const short kExtremeNeg = -32768;
  91. const short kExtremePos = 32767 - 1; // required to address an old region bug
  92.  
  93. // kMaxOpenDocuments is used to determine whether a new document can be opened
  94. // or created. We keep track of the number of open documents, and disable the
  95. // menu items that create a new document when the maximum is reached. If the
  96. // number of documents falls below the maximum, the items are enabled again. */
  97. const short    kMaxOpenDocuments = 1;
  98.     
  99. // Define HiWrd and LoWrd macros for efficiency.
  100. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  101. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  102.  
  103. // Our application object, initialized in main(). We make it
  104. // global so our functions which don't belong to any class
  105. // can find the active document.
  106. TShapesApp *gTheApplication;
  107.  
  108. // main is the entrypoint to the program
  109. int main(void)
  110. {
  111.     // Create our application object. This MUST be the FIRST thing
  112.     // done in main(), since it initializes the Toolbox for us.
  113.     gTheApplication = new TShapesApp;
  114.     if (gTheApplication == nil)        // if we couldn't allocate object (impossible!?)
  115.       return 0;                        // go back to Finder
  116.     
  117.     // Start our main event loop running. This won't return until user quits
  118.     gTheApplication->EventLoop();
  119.  
  120.     // We always return a value, like good little ANSI worshippers
  121.     return 0;
  122. }
  123.  
  124. // the constructor for our class, called automatically when we create
  125. // an instance of this class. In this particular case, we only want
  126. // one instance since the constructor does all the menu setups and
  127. // creates our (untitled) document.
  128. TShapesApp::TShapesApp(void)
  129. {
  130.     Handle    menuBar;
  131.  
  132.     // read menus into menu bar
  133.     menuBar = GetNewMBar(rMenuBar);
  134.     // install menus
  135.     SetMenuBar(menuBar);
  136.     DisposHandle(menuBar);
  137.     // add DA names to Apple menu
  138.     AddResMenu(GetMHandle(mApple), 'DRVR');
  139.     DrawMenuBar();
  140.  
  141.     // create empty mouse region
  142.     fMouseRgn = NewRgn();
  143.     // create a single empty document
  144.     DoNew();
  145. }
  146.  
  147. // Tell TApplication class how much heap we need
  148. long TShapesApp::HeapNeeded(void)
  149. {
  150.     return (kMinSize * 1024);
  151. }
  152.  
  153. // Calculate a sleep value for WaitNextEvent. This takes into account the things
  154. // that DoIdle does with idle time.
  155.  
  156. unsigned long TShapesApp::SleepVal(void)
  157. {
  158.     unsigned long sleep;
  159.     const long kSleepTime = 0x7fffffff;    // a very large positive number
  160.  
  161.     sleep = kSleepTime;                // default value for sleep
  162.     if ((!fInBackground))
  163.     {
  164.           sleep = GetCaretTime();    // A reasonable time interval for MenuClocks, etc.
  165.     }
  166.     return sleep;
  167. }
  168.  
  169. // Enable and disable menus based on the current state. The
  170. // user can only select enabled menu items. We set up all the
  171. // menu items before calling MenuSelect or MenuKey, since
  172. // these are the only times that a menu item can be selected.
  173. // Note that MenuSelect is also the only time the user will
  174. // see menu items. This approach to deciding what enable/
  175. // disable state a menu item has the advantage of
  176. // concentrating all the decision-making in one routine, as
  177. // opposed to being spread throughout the application. Other
  178. // application designs may take a different approach that may
  179. // or may not be as valid. 
  180.  
  181. void TShapesApp::AdjustMenus(void)
  182. {
  183.     WindowPtr    frontmost;
  184.     MenuHandle    menu;
  185.     Boolean        undo;
  186.     Boolean        cutCopyClear;
  187.     Boolean        paste;
  188.     Boolean        shape, move;
  189.     TShapesDocument* fShapesCurDoc = (TShapesDocument*) fCurDoc;
  190.  
  191.     frontmost = FrontWindow();
  192.  
  193.     menu = GetMHandle(mFile);
  194.     if ( fDocList->NumDocs() < kMaxOpenDocuments )
  195.       EnableItem(menu, iNew);            // New is enabled when we can open more documents 
  196.     else DisableItem(menu, iNew);
  197.     if ( frontmost != (WindowPtr) nil )    // Close is enabled when there is a window to close 
  198.       EnableItem(menu, iClose);
  199.     else DisableItem(menu, iClose);
  200.  
  201.     undo = false;
  202.     cutCopyClear = false;
  203.     paste = false;
  204.     shape = false;
  205.     move = false;
  206.     
  207.     if ( fShapesCurDoc == nil )
  208.       {
  209.         undo = true;                // all editing is enabled for DA windows 
  210.         cutCopyClear = true;
  211.         paste = true;
  212.       }
  213.     else
  214.       {
  215.         shape = true;
  216.         if (fShapesCurDoc->HasShape()) move = true;
  217.       }
  218.       
  219.     menu = GetMHandle(mEdit);
  220.     if ( undo )
  221.         EnableItem(menu, iUndo);
  222.     else
  223.         DisableItem(menu, iUndo);
  224.     
  225.     if ( cutCopyClear )
  226.       {
  227.         EnableItem(menu, iCut);
  228.         EnableItem(menu, iCopy);
  229.         EnableItem(menu, iClear);
  230.       } 
  231.     else
  232.       {
  233.         DisableItem(menu, iCut);
  234.         DisableItem(menu, iCopy);
  235.         DisableItem(menu, iClear);
  236.       }
  237.       
  238.     if ( paste )
  239.         EnableItem(menu, iPaste);
  240.     else
  241.         DisableItem(menu, iPaste);
  242.         
  243.     menu = GetMHandle(mShapes);
  244.     if ( shape )
  245.       {
  246.         EnableItem(menu, iRRect);
  247.         EnableItem(menu, iOval);
  248.         EnableItem(menu, iArc);
  249.       }
  250.     else
  251.       {
  252.         DisableItem(menu, iRRect);
  253.         DisableItem(menu, iOval);
  254.         DisableItem(menu, iArc);
  255.       }
  256.         
  257.     if ( move )
  258.         EnableItem(menu, iMove);
  259.     else
  260.         DisableItem(menu, iMove);
  261.     
  262. } // AdjustMenus
  263.  
  264.  
  265. // This is called when an item is chosen from the menu bar (after calling
  266. // MenuSelect or MenuKey). It does the right thing for each command.
  267.  
  268. void TShapesApp::DoMenuCommand(short menuID, short menuItem)
  269. {
  270.     short        itemHit;
  271.     Str255        daName;
  272.     short        daRefNum;
  273.     WindowPtr    window;
  274.     Rect        moveRect;
  275.     TShapesDocument* fShapesCurDoc = (TShapesDocument*) fCurDoc;
  276.  
  277.     window = FrontWindow();
  278.     switch ( menuID )
  279.       {
  280.         case mApple:
  281.             switch ( menuItem )
  282.               {
  283.                 case iAbout:        // bring up alert for About 
  284.                     itemHit = Alert(rAboutAlert, nil);
  285.                     break;
  286.                 default:            // all non-About items in this menu are DAs et al 
  287.                     GetItem(GetMHandle(mApple), menuItem, daName);
  288.                     daRefNum = OpenDeskAcc(daName);
  289.                     break;
  290.               }
  291.             break;
  292.         case mFile:
  293.             switch ( menuItem )
  294.               {
  295.                 case iNew:
  296.                     DoNew();
  297.                     break;
  298.                 case iClose:
  299.                     if (fShapesCurDoc != nil)
  300.                       {
  301.                         fDocList->RemoveDoc(fShapesCurDoc);
  302.                         delete fShapesCurDoc;
  303.                       }
  304.                     else CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
  305.                     break;
  306.                 case iQuit:
  307.                     Terminate();
  308.                     break;
  309.               }
  310.             break;
  311.         case mEdit:                    // call SystemEdit for DA editing & MultiFinder 
  312.             if ( !SystemEdit(menuItem-1) )
  313.               {
  314.                 switch ( menuItem )
  315.                   {
  316.                     case iCut:
  317.                         break;
  318.                     case iCopy:
  319.                         break;
  320.                     case iPaste:
  321.                         break;
  322.                     case iClear:
  323.                         break;
  324.                    }
  325.               }
  326.             break;
  327.         case mShapes:
  328.             switch ( menuItem )
  329.               {
  330.                 case iMove:
  331.                     if (fShapesCurDoc != nil && fShapesCurDoc->HasShape()) {
  332.                         // Get the window size to constrain the move
  333.                         moveRect = (fShapesCurDoc->GetDocWindow())->portRect;
  334.                         
  335.                         fShapesCurDoc->GetShape()->Erase();
  336.                         fShapesCurDoc->GetShape()->Move(&moveRect);
  337.                         fShapesCurDoc->GetShape()->Draw(qd.gray);
  338.                     }
  339.                     break;
  340.                 default:
  341.                     if (fShapesCurDoc != nil)
  342.                         fShapesCurDoc->ChangeShape(menuItem);
  343.                     break;
  344.                }
  345.             break;
  346.       }
  347.     HiliteMenu(0);                    // unhighlight what MenuSelect (or MenuKey) hilited 
  348. } // DoMenuCommand
  349.  
  350. // Create a new document and window. 
  351.  
  352. void TShapesApp::DoNew(void)
  353. {
  354.     TShapesDocument* tShapesDoc;
  355.     
  356.     tShapesDoc = new TShapesDocument(rDocWindow);
  357.     // if we didn't get an allocation error, add it to list
  358.     if (tShapesDoc != nil)
  359.       fDocList->AddDoc(tShapesDoc);
  360. } // DoNew
  361.  
  362. // Clean up the application and exits. We close all of the windows so that
  363. // they can update their documents.
  364.  
  365. void TShapesApp::Terminate(void)
  366. {
  367.     // FIX: close all docs
  368.     ExitLoop();
  369. } // Terminate
  370.  
  371.